package org.dromara.finance.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.finance.domain.CustomerCategory;
import org.dromara.finance.domain.Staff;
import org.dromara.finance.mapper.SupplierMapper;
import org.springframework.stereotype.Service;
import org.dromara.finance.domain.bo.SupplierCategoryBo;
import org.dromara.finance.domain.vo.SupplierCategoryVo;
import org.dromara.finance.domain.SupplierCategory;
import org.dromara.finance.mapper.SupplierCategoryMapper;
import org.dromara.finance.service.ISupplierCategoryService;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 供应商分类Service业务层处理
 *
 * @author xxy
 * @date 2025-08-15
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class SupplierCategoryServiceImpl implements ISupplierCategoryService {

    private final SupplierCategoryMapper baseMapper;

    private final SupplierMapper supplierMapper;

    /**
     * 查询供应商分类
     *
     * @param id 主键
     * @return 供应商分类
     */
    @Override
    public SupplierCategoryVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }


    /**
     * 查询符合条件的供应商分类列表
     *
     * @param bo 查询条件
     * @return 供应商分类列表
     */
    @Override
    public List<SupplierCategoryVo> queryList(SupplierCategoryBo bo) {
        LambdaQueryWrapper<SupplierCategory> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<SupplierCategory> buildQueryWrapper(SupplierCategoryBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<SupplierCategory> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(SupplierCategory::getId);
        lqw.eq(StringUtils.isNotBlank(bo.getCode()), SupplierCategory::getCode, bo.getCode());
        lqw.like(StringUtils.isNotBlank(bo.getName()), SupplierCategory::getName, bo.getName());
        lqw.eq(bo.getPid() != null, SupplierCategory::getPid, bo.getPid());
        lqw.eq(bo.getSupplierCategoryStatus() != null, SupplierCategory::getSupplierCategoryStatus, bo.getSupplierCategoryStatus());
        return lqw;
    }

    /**
     * 新增供应商分类
     *
     * @param bo 供应商分类
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(SupplierCategoryBo bo) {
        SupplierCategory add = MapstructUtils.convert(bo, SupplierCategory.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改供应商分类
     *
     * @param bo 供应商分类
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(SupplierCategoryBo bo) {
        SupplierCategory update = MapstructUtils.convert(bo, SupplierCategory.class);
        validEntityBeforeSave(update);
        //父子分类启用禁用校验
        SupplierCategory origin = baseMapper.selectById(update.getId());
        Long newStatus = update.getSupplierCategoryStatus();
        Long oldStatus = origin.getSupplierCategoryStatus();
        // 判断是否修改了状态
        if (!newStatus.equals(oldStatus)) {
            if (newStatus == 1) {
                // 启用：向上检查父级是否停用
                checkParentAllEnabled(update.getPid());
            } else if (newStatus == 2) {
                // 停用：向下检查子级是否还有启用，及供应商是否还启用
                checkChildrenAllDisabled(update.getId());
                checkSuppliersAllDisabled(update.getId());
            }
        }
        return baseMapper.updateById(update) > 0;
    }
    //启用时校验上级是否全部启用
    private void checkParentAllEnabled(Long pid) {
        while (pid != null && pid != 0) {
            SupplierCategory parent = baseMapper.selectById(pid);
            if (parent == null) break;
            if (parent.getSupplierCategoryStatus() == 2) {
                throw new ServiceException("上级分类【" + parent.getName() + "】已停用，无法启用！");
            }
            pid = parent.getPid();
        }
    }
    //停用时检查子分类是否还有启用状态
    private void checkChildrenAllDisabled(Long categoryId) {
        List<SupplierCategory> children = baseMapper.selectChildren(categoryId);
        for (SupplierCategory child : children) {
            if (child.getSupplierCategoryStatus() == 1) {
                throw new ServiceException("存在启用中的子分类,无法停用！");
            }
        }
    }
    //停用时检查是否有启用中的供应商
    private void checkSuppliersAllDisabled(Long categoryId) {
        int count = supplierMapper.countEnabledByCategoryId(categoryId); // 返回启用供应商数量
        if (count > 0) {
            throw new ServiceException("该分类下存在启用中的供应商，无法停用！");
        }
    }
    public List<SupplierCategory> selectCategoryListExcludeChild(Long categoryId) {
        // 查询全部分类
        List<SupplierCategory> allCategories = baseMapper.selectList();

        // 获取要排除的ID集合：自身 + 所有子节点
        Set<Long> excludeIds = getChildIds(allCategories, categoryId);
        excludeIds.add(categoryId); // 加上自己

        // 过滤
        return allCategories.stream()
            .filter(cat -> !excludeIds.contains(cat.getId()))
            .collect(Collectors.toList());
    }
    /*public List<SupplierCategory> selectListIgnoreParent() {
        return baseMapper.selectListIgnoreParent();
    }*/

    public boolean hasChildByCategoryId(Long id) {
        int result = baseMapper.hasChildByCategoryId(id);
        return result > 0;
    }

    public boolean checkSupplierCategoryExistSupplier(Long id) {
        int result = baseMapper.checkSupplierCategoryExistSupplier(id);
        return result > 0;
    }

    //递归查询子分类
    private Set<Long> getChildIds(List<SupplierCategory> allList, Long parentId) {
        Set<Long> result = new HashSet<>();
        for (SupplierCategory cat : allList) {
            if (Objects.equals(cat.getPid(), parentId)) {
                result.add(cat.getId());
                result.addAll(getChildIds(allList, cat.getId()));
            }
        }
        return result;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(SupplierCategory entity){
        //TODO 做一些数据校验,如唯一约束
        QueryWrapper<SupplierCategory> wrapper = new QueryWrapper<>();
        wrapper.eq("code", entity.getCode());

        // 如果是修改，排除自身
        if (entity.getId() != null) {
            wrapper.ne("id", entity.getId());
        }

        Long count = baseMapper.selectCount(wrapper);
        if (count != null && count > 0) {
            throw new RuntimeException("供应商分类编码已存在");
        }
    }

    /**
     * 校验并批量删除供应商分类信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
            for (Long id : ids) {
                if (hasChildByCategoryId(id)){
                    throw new ServiceException("存在子分类,无法删除！");
                }
                if (checkSupplierCategoryExistSupplier(id)) {
                    throw new ServiceException("该分类下存在供应商，无法删除！");
                }
            }
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    @Override
    public List<SupplierCategoryVo> queryIgnoreParentList(SupplierCategoryBo bo) {
        LambdaQueryWrapper<SupplierCategory> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(SupplierCategory::getId);
        lqw.eq(SupplierCategory::getSupplierCategoryStatus,1);
        lqw.notInSql(SupplierCategory::getId, "SELECT pid FROM supplier_category WHERE pid IS NOT NULL");
        return baseMapper.selectVoList(lqw);
    }
}
